#ifndef CXX_STUDY_STRING_HPP
#define CXX_STUDY_STRING_HPP

#include <cstdlib>
#include <memory.h>

namespace cxx_study {

  /**
   * 字符串
   * */
  class string {
    friend std::ostream &operator<<(std::ostream &ostream, const string &rhs);

  public:
    string() : buf(nullptr), buf_size(0), size(0) {}

    ~string() { if (buf)free(buf); }

    string(const char *rhs) {
      size = strlen(rhs);
      buf = (char *) malloc(buf_size = size + 1);
      memcpy(buf, rhs, buf_size);
    }

    string(const string &rhs) {
      if (rhs.buf) {
        size = rhs.size;
        buf = (char *) malloc(buf_size = size + 1);
        memcpy(buf, rhs.buf, buf_size);
      } else {
        size = buf_size = 0;
        buf = nullptr;
      }
    }

    string(string &&rhs) noexcept {
      size = rhs.size;
      buf_size = rhs.buf_size;
      buf = rhs.buf;

      rhs.size = 0;
      rhs.buf_size = 0;
      rhs.buf = nullptr;
    }

    string &operator=(const char *rhs) {
      size = strlen(rhs);
      if (buf == nullptr)
        buf = (char *) malloc(buf_size = size + 1);
      else if (buf_size < size + 1)
        buf = (char *) realloc(buf, buf_size = size + 1);

      memcpy(buf, rhs, size + 1);
    }

    string &operator=(const string &rhs) {
      if (this == &rhs)return *this;
      string tmp(rhs);
      swap(tmp);
      return *this;
    }

    void swap(string &rhs) {
      std::swap(buf, rhs.buf);
      std::swap(buf_size, rhs.buf_size);
      std::swap(size, rhs.size);
    }

    inline const char &operator[](const std::size_t &index) const {
      return buf[index];
    }

    inline char &operator[](const std::size_t &index) {
      return buf[index];
    }

  private:
    char *buf;
    std::size_t buf_size;
    std::size_t size;
  };

  std::ostream &operator<<(std::ostream &ostream, const string &rhs) {
    if (rhs.buf) ostream << rhs.buf;
    return ostream;
  }
}

#endif //CXX_STUDY_STRING_HPP
